package controllers;

import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import models.Barang;
import models.Kategori;
import models.Pesanan;
import models.PesananItem;
import models.User;
import system.Controller;
import system.MailServer;
import system.SchedulerTask;
import system.WebService;

/**
 *
 * @author Rezan Achmad
 */
@WebServlet(name = "SiteController", urlPatterns = {"/site", "/site/index", "/site/logout", "/site/login", "/site/barang",
    "/site/cart", "/site/cart/addItem", "/site/cart/deleteItem", "/site/cart/updateItem", "/site/cart/save", "/site/cart/tukarPoin"})
public class SiteController extends Controller {

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        SchedulerTask.scheduleNotification();
    }

    @Override
    protected void initRules() {
        // Guest
        rules.put("/site/login", identity.isGuest());

        // Non Guest
        rules.put("/site/logout", !identity.isGuest());
        rules.put("/site/cart", !identity.isGuest());
        rules.put("/site/cart/addItem", !identity.isGuest());
        rules.put("/site/cart/deleteItem", !identity.isGuest());
        rules.put("/site/cart/updateItem", !identity.isGuest());
        rules.put("/site/cart/save", !identity.isGuest());
    }

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

        String userPath = request.getServletPath();

        if (userPath.equals("/site/logout")) {
            actionLogout(request, response);
        } else if (userPath.equals("/site/login")) {
            actionLogin(request, response);
        } else if (userPath.equals("/site")) {
            //setView("/site/index", request, response);
            actionMainView(request, response);
        } else if (userPath.equals("/site/index")) {
            actionMainView(request, response);
        } else if (userPath.equals("/site/barang")) {
            if (isGet) {
                // TODO get
                if (request.getParameter("barang_id") != null) {
                    Barang foundItem = Barang.get(Integer.parseInt(request.getParameter("barang_id")));
                    if (foundItem != null) {
                        request.setAttribute("object", foundItem);
                        request.setAttribute("listKategori", Kategori.getAll());
                        setView("/site/barang", request, response);
                    } else {
                        userPath = "/site/index";
                        actionMainView(request, response);
                    }
                } else {
                    userPath = "/site/index";
                    actionMainView(request, response);
                }
            }
        } else if (userPath.equals("/site/cart")) {
            actionCart(request, response);
        } else if (userPath.equals("/site/cart/addItem")) {
            actionCart(request, response);
        } else if (userPath.equals("/site/cart/deleteItem")) {
            actionCart(request, response);
        } else if (userPath.equals("/site/cart/updateItem")) {
            actionCart(request, response);
        } else if (userPath.equals("/site/cart/save")) {
            actionCart(request, response);
        } else if (userPath.equals("/site/cart/tukarPoin")) {
            actionCart(request, response);
        }
    }

    protected void actionMainView(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ArrayList<Barang> listBarang = new ArrayList<Barang>();
        ArrayList<Kategori> listKategori = Kategori.getAll();
        int itemPerPage = 9;
        int totalItem = 0;

        // Page
        int page = 0;
        try {
            page = Integer.parseInt(request.getParameter("page"));
        } catch (Exception e) {
        }

        if (isGet) {
            String keywords = request.getParameter("keywords");
            boolean isAvailKeywords = (keywords != null && !"".equals(keywords));
            if (request.getParameter("kategori_id") != null) {
                Integer kategori_id = Integer.parseInt(request.getParameter("kategori_id"));
                if (isAvailKeywords) {
                    System.out.println("avail");
                    listBarang = Barang.getAllByCategory(keywords, kategori_id, page * itemPerPage, itemPerPage);
                    totalItem = Barang.getInstance().getCountByKategori(keywords, kategori_id);
                } else {
                    listBarang = Barang.getAllByCategory(kategori_id, page * itemPerPage, itemPerPage);
                    totalItem = Barang.getInstance().getCountByKategori(kategori_id);
                }
            } else {
                if (isAvailKeywords) {
                    System.out.println("avail");
                    listBarang = Barang.getAll(keywords, page * itemPerPage, itemPerPage);
                    totalItem = Barang.getInstance().getCount(keywords);
                } else {
                    listBarang = Barang.getAll(page * itemPerPage, itemPerPage);
                    totalItem = Barang.getInstance().getCount();
                }
            }
        }

        request.setAttribute("listBarang", listBarang);
        request.setAttribute("listKategori", listKategori);
        request.setAttribute("itemPerPage", itemPerPage);
        request.setAttribute("totalItem", totalItem);

        setView("/site/index", request, response);
    }

    protected void actionLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        User user = new User();
        request.setAttribute("user", user);

        if (isPost) {
            user.email = (String) request.getParameter("email");
            user.password = (String) request.getParameter("password");

            if (user.authenticate()) {
                // Get user
                user = User.getByEmail(user.email);

                // Set session
                request.getSession(true).setAttribute("email", user.email);
                request.getSession(true).setAttribute("nama_panggilan", user.nama_panggilan);
                request.getSession(true).setAttribute("user_id", user.id);
                request.getSession(true).setAttribute("role_id", user.role_id);
                request.getSession(true).setAttribute("user_point", user.point);
                request.getSession(true).setAttribute("user_address", user.alamat);

                // Redirect
                response.sendRedirect(request.getContextPath());
                return;
            }

            // Add error
            user.addError("password", "email dan password tidak cocok");
        }

        setView("/site/login", request, response);
    }

    protected void actionLogout(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // Destroy session
        destroySession(request);

        // Redirect
        response.sendRedirect(request.getContextPath());
        return;
    }

    protected void actionCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userPath = request.getServletPath();

        if (request.getSession().getAttribute("email") != null) {

            // Get user instance
            User user = User.getByEmail((String) request.getSession().getAttribute("email"));
            Pesanan pesanan = Pesanan.getLastActivePesanan(user.id);
            pesanan.status = Pesanan.STATUS_INCART;
            pesanan.user_id = user.id;
            pesanan.add();

            if (userPath.equals("/site/cart")) {
                // view only, do nothing
            } else if (userPath.equals("/site/cart/addItem")) {
                // add item to current pesanan
                if (isPost) {
                    PesananItem pi = new PesananItem();

                    // Set attribute
                    pi.pesanan_id = pesanan.id;
                    pi.barang_id = Integer.parseInt(request.getParameter("itemID"));
                    pi.jumlah = 1;

                    // Get barang
                    Barang barang = Barang.get(pi.barang_id);

                    // Set harga satuan
                    pi.harga_satuan = barang.harga_satuan;

                    if (barang.jumlah >= pi.jumlah) {
                        pi.add();
                    }
                }
            } else if (userPath.equals("/site/cart/deleteItem")) {
                // delete item from current pesanan
                if (isGet) {
                    int pesananID = Integer.parseInt(request.getParameter("pesananID"));
                    int barangID = Integer.parseInt(request.getParameter("itemID"));
                    PesananItem instance = PesananItem.getInstance().getById(pesananID, barangID);
                    if (instance != null) {
                        instance.delete();
                    }
                }
            } else if (userPath.equals("/site/cart/updateItem")) {
                // update item in current pesanan
                // 1. ambil semua list dalam cart database
                // 2. cek data, kalo ada yang berubah update
                ArrayList<PesananItem> tempList = PesananItem.getInstance().getAllByPesananId(pesanan.id);
                for (int i = 0; i < tempList.size(); ++i) {
                    PesananItem newPesananItem = tempList.get(i);
                    int newJumlah = Integer.parseInt((String) request.getParameter("jumlah_" + tempList.get(i).barang_id));
                    if (newPesananItem.jumlah != newJumlah) {
                        newPesananItem.jumlah = newJumlah;
                        if (!newPesananItem.update()) {
                            request.setAttribute("status_pesanan", "Satu atau beberapa barang stoknya kurang, gagal diupdate!");
                        }
                    }
                }
            } else if (userPath.equals("/site/cart/save")) {
                // update apa pesanan ingin dikirim atau tidak
                pesanan.kirim = Integer.parseInt(request.getParameter("statusKirim"));
                pesanan.alamat_kirim = request.getParameter("alamatKirim");
                if(pesanan.kirim == 1) {
                    try {
                        pesanan.shipping_service_id = Integer.parseInt(request.getParameter("shipping_id"));
                    }catch(Exception e){
                    }
                }
                pesanan.update();

                // save cart, update status in current pesanan
                pesanan.addPoin();
                user = User.getByEmail(user.email);
                request.getSession(true).setAttribute("user_point", user.point);
                if (pesanan.saveCart()) {
                    sendEmailNewPesanan(pesanan);
                }
                response.sendRedirect(request.getContextPath());
                return;
            } else if (userPath.equals("/site/cart/tukarPoin")) {
                // menambahkan diskon ke pesanan
                if (User.tukarPoin((String) request.getSession().getAttribute("email"))) {
                    user = User.getByEmail(user.email);
                    request.getSession(true).setAttribute("user_point", user.point);
                    pesanan.diskon = 10;
                    pesanan.update();
                } else {
                    request.setAttribute("status_pesanan", "Penukaran poin gagal! Periksa kembali poin Anda!");
                }
            }

            ArrayList<PesananItem> listPesananItem = PesananItem.getInstance().getAllByPesananId(pesanan.id);
            request.setAttribute("pesananID", pesanan);
            request.setAttribute("listPesananItem", listPesananItem);
            request.setAttribute("shippingServices", WebService.getShippingServices());
            setView("/site/cart", request, response);
        } else {
            response.sendRedirect(request.getContextPath());
            return;
        }
    }

    protected void destroySession(HttpServletRequest request) {
        HttpSession session = request.getSession(false);

        // Destroy session
        if (session != null) {
            synchronized (session) {
                session.invalidate();
            }
        }
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }

    /**
     * Mengirim email ke pemesanan dan pegawai jika terdapat pesanan baru.
     * @param pesanan 
     */
    private void sendEmailNewPesanan(Pesanan pesanan) {
        ArrayList<PesananItem> items = pesanan.getPesananItems();
        Barang barang;
        User user = pesanan.getUser();
        int hargaTotal, subTotal = 0, potongan = 0, hoursToExpired = 48;

        StringBuilder subject = new StringBuilder();
        StringBuilder message = new StringBuilder();

        // Email untuk pemesan
        String to[] = new String[]{user.email};
        subject.append("Pesanan Baru ID ").append(pesanan.id);

        message.append("Hai ").append(user.nama_lengkap).append(",\n\n");
        message.append("Terima kasih atas pesanan anda di toko kami. Berikut detail pesanan Anda :\n\n");
        message.append("Pesanan ID : ").append(pesanan.id).append("\n\n");
        message.append("Nama Barang / Jumlah / Harga Satuan / Harga Total\n");
        for (PesananItem item : items) {
            barang = Barang.get(item.barang_id);
            hargaTotal = item.jumlah * item.harga_satuan;
            subTotal += hargaTotal;
            message.append(barang.nama).append(" / ").append(item.jumlah).append(" / ").append(item.harga_satuan).append(" / ").append(hargaTotal).append("\n");
        }
        potongan = pesanan.diskon * subTotal / 100;
        message.append("\nSub Total : Rp. ").append(subTotal).append("\n");
        message.append("Potongan : Rp. ").append(potongan).append("\n");
        message.append("Total Bayar : Rp. ").append(subTotal - potongan).append("\n\n");
        message.append("Segera lakukan pembayaran maksimal ").append(hoursToExpired).append(" jam dari sekarang.\n");
        message.append("Jika Anda tidak membayar dalam masa waktu tersebut, kami akan membatalkan pesanan ini.");

        // Kirim email ke pemesan
        MailServer.sendEmail(to, subject.toString(), message.toString());

        // Isi email untuk pegawai
        message = new StringBuilder();
        message.append("Kepada Seluruh Pegawai,\n\n");
        message.append("Terdapat pesanan baru dengan ID ").append(pesanan.id).append(" dari pelanggan ").append(user.nama_lengkap).append(".\n");
        message.append("Detail pesanan dapat dilihat melalui sistem.");

        // Kirim email ke pegawai
        MailServer.sendEmail(User.getInstance().getAllEmailPegawai(), subject.toString(), message.toString());
    }
}
